﻿#include <utility>

#include <string>
#include <stack>
#include <set>
//
// Created by hujin on 2020/9/21.
//

#ifndef C_MIPS_CMPLR_TOKEN_H
#define C_MIPS_CMPLR_TOKEN_H




enum Symbol {
	/*标识符*/IDENFR,
	/*整形常量*/INTCON,
	/*字符常量*/CHARCON,
	/*字符串*/STRCON,
	/*const*/CONSTTK,
	/*int*/INTTK,
	/*char*/CHARTK,
	/*void*/VOIDTK,
	/*main*/MAINTK,
	/*if*/IFTK,


	/*else*/ELSETK,
	/*switch*/SWITCHTK,
	/*case*/CASETK,
	/*default*/DEFAULTTK,
	/*while*/WHILETK,
	/*for*/FORTK,
	/*scanf*/SCANFTK,
	/*printf*/PRINTFTK,
	/*return*/RETURNTK,

	/*+*/PLUS,
	/*-*/MINU,
	/* * */MULT,
	/* / */DIV,
	/*<=*/LEQ, //**调整了顺序 **
	/*>=*/GEQ,
	/*<*/LSS,
	/*>*/GRE,
	/*==*/EQL,
	/*!=*/NEQ,
	/*：*/COLON,

	/*=*/ASSIGN,
	/*;*/SEMICN,
	/*,*/COMMA,
	/*(*/LPARENT,
	/*)*/RPARENT,
	/*[*/LBRACK,
	/*]*/RBRACK,
	/*{*/LBRACE,
	/*}*/RBRACE,
	BAD, ENDFILE

};
const std::string SYMBOL_NAMES[100] = {
		"IDENFR",
		"INTCON",
		"CHARCON",
		"STRCON",
		"CONSTTK",
		"INTTK",
		"CHARTK",
		"VOIDTK",
		"MAINTK",
		"IFTK",


		"ELSETK",
		"SWITCHTK",
		"CASETK",
		"DEFAULTTK",
		"WHILETK",
		"FORTK",
		"SCANFTK",
		"PRINTFTK",
		"RETURNTK",
		"PLUS",

		"MINU",
		"MULT",
		"DIV",
		"LEQ",
		"GEQ",
		"LSS",
		"GRE",
		"EQL",
		"NEQ",
		"COLON",

		"ASSIGN",
		"SEMICN",
		"COMMA",
		"LPARENT",
		"RPARENT",
		"LBRACK",
		"RBRACK",
		"LBRACE",
		"RBRACE"
};

bool isRelationSymbol(Symbol symbol);

const std::string templates[100] = {
		"标识符",//0
		"整形常量",//1
		"字符常量",//2
		"字符串",//3
		"const",//4
		"int",
		"char",
		"void",
		"main",
		"if",

		"else",
		"switch",
		"case",
		"default",
		"while",
		"for",
		"scanf",
		"printf",
		"return",

		"+",
		"-",
		"*",
		"/",
		"<=",
		">=",
		"<",
		">",
		"==",
		"!=",
		":",

		"=",
		";",
		",",
		"(",
		")",
		"[",
		"]",
		"{",
		"}"

};
class Token {
public:
	Symbol symbol = ENDFILE;
	std::string string;
	union Data {
		char c; int i = 0;
	}data;
    std::string rawId;
	Token() = default;
	Token(Symbol symbol, std::string string) {
		this->string = std::move(string), this->symbol = symbol;
	}

};

class TokenChar : public Token {
public:
	explicit TokenChar(char c);
};

class TokenInt : public Token {
public:
	explicit TokenInt(std::string x, int i);
};

class TokenReader {
	int lineCnt = 1;
	std::stack<int> lastOffset;
	std::string str;
	int offset = 0;
public:
	bool error = false;
public:
	Token cur = Token{};
	explicit TokenReader(std::string& str) :str(std::move(str)) {};

	Token& nextToken();
	Token& curToken();

	void back();
	void logCurToken();
	~TokenReader() = default;

	int getLineCnt() const;
    int getPreLineCnt() const;
	int getPos();

    int getPrePos() const;
};

#endif //C_MIPS_CMPLR_TOKEN_H
